package rs.udd.service.document.searcher;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.mlt.MoreLikeThis;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.spell.DirectSpellChecker;
import org.apache.lucene.search.spell.SuggestWord;
import org.apache.lucene.util.Version;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFTextStripper;

import rs.udd.service.document.analyzer.SerbianAnalyzer;
import rs.udd.service.document.indexer.IndexManager;
import rs.udd.service.document.indexer.UDDIndexer;
import rs.udd.service.document.indexer.handler.PDFHandler;
import rs.udd.service.document.model.RequiredHighlight;
import rs.udd.service.dto.search.SearchAdvertsResultDto;
import rs.udd.service.util.FileUtil.FileTypes;

public class InformationRetriever {

	private static int maxHits = 10;
	private static final Version matchVersion = Version.LUCENE_4_9;
	private static Analyzer analyzer = new SerbianAnalyzer(matchVersion);

	public static List<SearchAdvertsResultDto> getData(Query query, List<RequiredHighlight> requiredHighlights) {
		if (query == null)
			return null;
		List<Document> docs = ResultRetriever.getResults(query);
		List<SearchAdvertsResultDto> results = new ArrayList<SearchAdvertsResultDto>();

		String temp;
		SearchAdvertsResultDto data;
		Highlighter hl;
		DirectoryReader reader;
		try {
			reader = DirectoryReader.open(IndexManager.getIndexer().getIndexDir());
			for (Document doc : docs) {
				String[] documentTypes = doc.getValues(PDFHandler.TYPE);
				boolean isAdvert = PDFHandler.checkType(documentTypes, FileTypes.ADVERT);
						
				if (!isAdvert)
					continue;
					
				data = new SearchAdvertsResultDto();

				String documentId = doc.get(PDFHandler.ID);
				data.setDocumentId(documentId);

				String[] allKeywords = doc.getValues(PDFHandler.KEY_WORD);
				temp = "";
				for (String keyword : allKeywords) {
					temp += keyword + ", ";
				}
				temp = temp.substring(0, temp.length() - 2);
				data.setKeywords(temp);

				data.setTitle(doc.get(PDFHandler.TITLE));
				data.setAuthor(doc.get(PDFHandler.AUTHOR));
				data.setLocation(doc.get(PDFHandler.LOCATION));

				temp = "";
				if (requiredHighlights != null) {
					for (RequiredHighlight rh : requiredHighlights) {
						try {
							hl = new Highlighter(new QueryScorer(query, reader, rh.getFieldName()));
//							File docFile = new File(doc.get(PDFHandler.LOCATION));
//							String value = UDDIndexer.getHandler(docFile, documentId).getDocument(docFile, null).get(rh.getFieldName());
							String value = doc.get(rh.getFieldName());
							String tempHL = hl.getBestFragment(analyzer, rh.getFieldName(), value);
							if (tempHL != null) {
								temp += rh.getFieldName() + ": " + tempHL.trim() + " ... ";
							}
						} catch (Exception e) {

						}
					}
				}
				data.setHighlight(temp);
				results.add(data);
			}
			reader.close();
			return results;
		} catch (IOException e) {
		}
		throw new IllegalArgumentException("U prosledjenom direktorijumu ne postoje indeksi ili je direktorijum zakljucan");
	}

	public static List<RequiredHighlight> getSuggestions(Term term) {
		if (term == null) {
			return null;
		}
		DirectoryReader reader;
		DirectSpellChecker dsc = new DirectSpellChecker();
		try {
			reader = DirectoryReader.open(IndexManager.getIndexer().getIndexDir());
			SuggestWord[] suggestions = dsc.suggestSimilar(term, maxHits, reader);
			List<RequiredHighlight> suggestedTerms = new ArrayList<RequiredHighlight>();
			for (SuggestWord sw : suggestions) {
				suggestedTerms.add(new RequiredHighlight(term.field(), sw.string, null));
			}
			return suggestedTerms;
		} catch (Exception e) {
		}

		throw new IllegalArgumentException("U prosledjenom direktorijumu ne postoje indeksi ili je direktorijum zakljucan");
	}

	public static List<SearchAdvertsResultDto> getMoreLikeThis(String filePath) {
//		File docFile = new File(documentId);
		List<SearchAdvertsResultDto> results = null;

		DirectoryReader dReader;
		try {
			File file = new File(filePath);
			String textFromFile = getTextFromFile(file);
//			String text = UDDIndexer.getHandler(docFile, null).getDocument(docFile).get(PDFHandler.TEXT);
			dReader = DirectoryReader.open(IndexManager.getIndexer().getIndexDir());

			MoreLikeThis mlt = new MoreLikeThis(dReader);
			mlt.setMinTermFreq(0);
			mlt.setMinDocFreq(0);
			mlt.setFieldNames(new String[] { PDFHandler.TEXT });
			mlt.setAnalyzer(analyzer);

			Reader sReader = new StringReader(textFromFile);
			Query query = mlt.like(PDFHandler.TEXT, sReader);

			results = getData(query, null);
			System.out.println("ok");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return results;
	}
	
	public static String getTextFromFile(File file) throws Exception {
		// napraviti pdf parser
		PDFParser parser = new PDFParser(new FileInputStream(file));
		// izvrsiti parsiranje
		parser.parse();
		// od parsera preuzeti parsirani pdf dokument (PDDocument)
		PDDocument pdf = parser.getPDDocument();

		// Upotrebiti text stripper klasu za ekstrahovanje teksta sa utf-8 kodnom stranom (PDFTextStripper)
		PDFTextStripper stripper = new PDFTextStripper("utf-8");
		String text = stripper.getText(pdf);
		
		pdf.close();
		
		return text;
	}

	public static void main(String[] args) {
		UDDIndexer indexer = IndexManager.getIndexer();
		indexer.index(new File("docs"), null);

		// suggestions
		Term term = new Term("text", "zacon");
		List<RequiredHighlight> s = InformationRetriever.getSuggestions(term);
		System.out.println("suggestions:");
		for (RequiredHighlight t : s) {
			System.out.println(t.getValue());
		}
		System.out.println();

		// highlights
		Term term2 = new Term("text", "zakon");
		TermQuery pq = new TermQuery(term2);
		List<RequiredHighlight> hls = new ArrayList<RequiredHighlight>();
		hls.add(new RequiredHighlight("text", "zakon", null));
		List<SearchAdvertsResultDto> data = InformationRetriever.getData(pq, hls);
		System.out.println("highlights:");
		for (SearchAdvertsResultDto dh : data) {
			System.out.println(dh.getHighlight());
			System.out.println("---");
		}
	}
}
